package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.factory.StrategyFactory;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.strategy.ItemTypeStrategy;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.joda.time.LocalDateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private WxMaService wxMaService;
    @Autowired
    private RabbitService rabbitService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;
    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;
    @Autowired
    private TrackInfoFeignClient trackInfoFeignClient;
    @Autowired
    private VipServiceConfigMapper vipServiceConfigMapper;
    @Autowired
    private UserVipServiceMapper userVipServiceMapper;
    @Autowired
    private StrategyFactory strategyFactory;

    @Override
    public void updateVipExpireStatus() {
        userInfoMapper.updateIsVip();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePaidRecord(UserPaidRecordVo userPaidRecordVo) {
        //记录用户购买信息
        ItemTypeStrategy itemTypeStrategy = strategyFactory.getStrategy(userPaidRecordVo.getItemType());
        itemTypeStrategy.savePaidRecord(userPaidRecordVo);
    }

    @Override
    public List<Long> findUserPaidTrackList(Long albumId, Long userid) {
        // 用户购买过的声音列表在user_paid_track
        List<Long> list =  userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>()
                .eq(UserPaidTrack::getUserId,userid)
                .eq(UserPaidTrack::getAlbumId,albumId))
                .stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
        //  返回用户购买的声音id列表
        return list;
    }

    @Override
    public Boolean isPaidAlbum(Long albumId, Long userid) {
        return null != userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>()
                .eq(UserPaidAlbum::getUserId,userid)
                .eq(UserPaidAlbum::getAlbumId,albumId));
    }

    @Override
    public Map<Long, Integer> userIsPaidTrack(Long albumId, List<Long> tracIdList, Long userid) {
        //创建map集合
        Map<Long,Integer> map = tracIdList.stream().collect(Collectors.toMap(trackId -> trackId,tracId -> 0));
        //判断用户是否购买过专辑从user_paid_album里面找     专辑！
        UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>()
                .eq(UserPaidAlbum::getUserId,userid).eq(UserPaidAlbum::getAlbumId,albumId));
        if(null != userPaidAlbum){
            // 当前用户有购买专辑  (trackId,状态1) 为已购买
            return tracIdList.stream().collect(Collectors.toMap(trackId-> trackId,trackId -> 1));
        }
        // 查询用户购买过的声音列表
        List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(
                new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId, userid)
                        .in(UserPaidTrack::getTrackId, tracIdList)
        );
        //判断是否为空
        if(!CollectionUtils.isEmpty(userPaidTrackList)){
            //购买过声音
            for (UserPaidTrack userPaidTrack : userPaidTrackList) {
                map.put(userPaidTrack.getTrackId(), 1);
            }
        }
        //返回数据
        return map;
    }

    @Override
    public void updateUser(Long userId, UserInfoVo userInfoVo) {
        // 修改用户信息
        UserInfo userInfo = new UserInfo();
        //  属性拷贝
        BeanUtils.copyProperties(userInfoVo, userInfo);
        userInfo.setId(userId);
        this.updateById(userInfo);
    }

    @Override
    public UserInfoVo getUserInfo(Long userId) {
        // 查询用户信息
        UserInfo userInfo = this.getById(userId);
        // 创建目标对象
        UserInfoVo userInfoVo = new UserInfoVo();
        // 拷贝
        BeanUtils.copyProperties(userInfo, userInfoVo);
        return userInfoVo;
    }

    @Override
    public Map<String, Object> wxLogin(String code) {
        //调用微信api
        WxMaJscode2SessionResult wxMaJscode2SessionResult = null;
        try {
            wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(code);
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        // openid 微信唯一标识
        String openid = wxMaJscode2SessionResult.getOpenid();
        // 利用openid 实现登录或注册功能
        UserInfo userInfo = userInfoMapper.selectOne(
                new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openid));
        // 判断对象是否为空
        if (null == userInfo) {
            //说明要注册 ： 本质就是赋值
            userInfo = new UserInfo();
            userInfo.setWxOpenId(openid);
            userInfo.setNickname("听友：" + System.currentTimeMillis());
            userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
            //	保存到数据库;
            userInfoMapper.insert(userInfo);
            //	在此需要给当前注册的用户进行初始化充值; 同步 异步 mq发送消息
            rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_USER_REGISTER, userInfo.getId());
        }
        // 说明要登录： 将数据存储到redis，与返回token;
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        //  组成缓存的key;
        String userLoginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
        //  存储数据;
        redisTemplate.opsForValue().set(userLoginKey, userInfo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
        // 	返回数据
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        return map;
    }
}
